-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
O(log n) lookup of associated items by name #69072
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Hopefully the up-front cost of sorting the associated items by name is outweighed by more efficient lookup. If this is not the case, I'll need to switch to an adaptive data structure or consider an out-of-band index that is interned separately. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
bb5ee1e
to
eb27aac
Compare
@bors try |
Awaiting bors try build completion |
⌛ Trying commit eb27aaca6450605ed78c29224c4351157357ffd8 with merge 8dc7de89edae6b4f434280089e1a14a36a1ab405... |
☀️ Try build successful - checks-azure |
Queued 8dc7de89edae6b4f434280089e1a14a36a1ab405 with parent 3f32e30, future comparison URL. |
Finished benchmarking try commit 8dc7de89edae6b4f434280089e1a14a36a1ab405, comparison URL. |
FYI syn-opt is nondeterministic right now: #69060 |
It's not a multi-map, but |
Looking at check builds, this PR is a slight regression. However, I think it is an acceptable one. I think we should merge this as-is to fix #68957. Those perf results suggest that name lookup is not a significant component of compile time for most crates, so I probably won't spend much time optimizing this PR. There are many improvements to be made if others are interested. Since the purpose of |
I would not replace in_definition_order (an incredibly useful name!) with iter at this point. |
I'm +1 on the approach: there's trivial perf degradation but the behavior in pathological cases is much more sane than it is now. I'll review more in depth soon. cc @rust-lang/compiler for visibility. |
src/librustc/ty/mod.rs
Outdated
// FIXME(ecstaticmorse): Audit uses of this method to see if the definition order is actually | ||
// significant in that context (perhaps we could replace them with calls to a newly defined | ||
// `in_arbitrary_order`?). Once all uses have been removed, `AssociatedItems` won't have to | ||
// keep a separate sorted list of indexes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be accomplished by actually randomizing the order of items_in_def_order
and see what breaks?
edited for clarity I added an I would like to only use To migrate away from |
O(log n)
lookup of associated items by name
We do have -Zui-testing I believe for the ability to change to "deterministic" mode.
cc @Centril -- this seems like something we could O(n) process in lang item collection and store HirIds or indices (whatever identified an associated item, I forget) like that for. |
cc @matthewjasper who has taken over my work on lang items in lowering and might have this more in cache. |
Some unrelated changes have dramatically sped up the pathological case in #68957 on recent nightlies. A local build of a recent master now takes 30 seconds, down from several minutes on 1.41.0. This PR is now just a 2x speedup instead of a 10x one. |
7a73fd3
to
186cbfa
Compare
Ok, it's still a single method whether it's called r=me with the nit (#69072 (comment)) addressed and green CI. |
@bors r+ |
📌 Commit a0212ba has been approved by |
☀️ Test successful - checks-azure |
📣 Toolstate changed by #69072! Tested on commit d3ebd59. 💔 clippy-driver on windows: test-fail → build-fail (cc @mcarton @oli-obk @Manishearth @flip1995 @yaahc @phansch @llogiq, @rust-lang/infra). |
Tested on commit rust-lang/rust@d3ebd59. Direct link to PR: <rust-lang/rust#69072> 💔 clippy-driver on windows: test-fail → build-fail (cc @mcarton @oli-obk @Manishearth @flip1995 @yaahc @phansch @llogiq, @rust-lang/infra). 💔 clippy-driver on linux: test-fail → build-fail (cc @mcarton @oli-obk @Manishearth @flip1995 @yaahc @phansch @llogiq, @rust-lang/infra).
Rustup to rust-lang/rust#69072 changelog: none
Resolves #68957, in which compile time is quadratic in the number of associated items. This PR makes name lookup use binary search instead of a linear scan to improve its asymptotic performance. As a result, the pathological case from that issue now runs in 8 seconds on my local machine, as opposed to many minutes on the current stable.
Currently, method resolution must do a linear scan through all associated items of a type to find one with a certain name. This PR changes the result of the
associated_items
query to a data structure that preserves the definition order of associated items (which is used, e.g., for the layout of trait object vtables) while adding an index of those items sorted by (unhygienic) name. When doing name lookup, we first find all items with the sameSymbol
using binary search, then run hygienic comparison to find the one we are looking for. Ideally, this would be implemented using an insertion-order preserving, hash-based multi-map, but one is not readily available.Someone who is more familiar with identifier hygiene could probably make this better by auditing the uses of the
AssociatedItems
interface. My goal was to preserve the current behavior exactly, even if it seemed strange (I left at least one FIXME to this effect). For example, some places use comparison withident.modern()
and some places usetcx.hygienic_eq
which requires theDefId
of the containingimpl
. I don't know whether those approaches are equivalent or which one should be preferred.